﻿let User = require("./User");
let gameDao = require("./../dao/gameDao");
let redis_dao = require("./../dao/redis_dao");
let arithmetic = require("./arithmetic")
let sever = require("./sever");
let schedule = require("node-schedule");
let gameConfig = require("./../config/gameConfig");
let log = require("./../../util/loginfo").getInstand;
let redis_send_and_listen = require("./../../util/redis_send_and_listen");

let GameInfo = function () {

    var _gameinfo = "";

    var Game = function () {

        //初始化算法，使用第X种
        this.initAlgorithm = function (idx) {
            log.info('####init Algorithm!####');
            log.info('use [' + idx + '] Algorithm!');
            this.A = new arithmetic(idx);
        };

        this.serverId = gameConfig.serverId;

        //初始化游戏
        this.init = function () {
            log.info('####init game!####');

            //初始化算法
            this.initAlgorithm(0);
            //初始化用户列表
            this.userList = {};
            //在线人数为0
            this.onlinePlayerCount = 0;
            //统计
            this.winTotal = 0;
            this.lotteryCount = 0;
            this.hourWinTotal = 0;
            this.hourlotteryCount = 0;

            //初始化清除数组
            redis_dao.init_bet_list();
            this.bet_time = 0;   //初始化下注时间
            this.qiang_time = 0;   //初始化抢庄时间
            this.feng_time = 0;   //初始化封盘时间

            this.game_record_list = [];   //游戏记录

            this.qiang_zhuang_list = [];  //抢庄数组

            this.zhuang_user = 0;  //庄家id

            this.score_changeLogList = [];
            this.lotteryLogList = [];
            this.lineOutList = [];
            //维护模式
            this.maintain = false;

            this.game_type = 3;    //游戏状态   0 默认   1开始下注  2 开奖   3结束  4开始抢庄 5封盘
            this.game_second = 0; //秒数
            this.zhuang_robot = false;  //庄是不是机器人
            this.bet_user_pool = [0, 0, 0, 0, 0, 0, 0, 0];

            this.sever = new sever();

            let rule = new schedule.RecurrenceRule();
            let times = [];
            for (let i = 0; i < gameConfig.gameTime; i++) {
                times.push(i);
            }
            rule.second = times;
            let self = this;
            schedule.scheduleJob(rule, function () {
                if (gameConfig.maintain) {
                    --gameConfig.maintainTime;
                    //log.info(gameConfig.maintainTime);;
                    if (!gameConfig.maintainTime) {
                        self.disconnectAllUser();
                    }
                }

                self.score_changeLog();
                self.lotteryLog();
                let nowDate = new Date();
                let second = nowDate.getSeconds();

                if (self.game_type === 3 && !self.zhuang_user && self.onlinePlayerCount > 0) {   //开始抢庄
                    log.info("开始抢庄");
                    self.game_type = 4;
                    self.qiang_time = gameConfig.qzTime;   //设置倒计时
                    self._io.sockets.emit('qiangStart', {
                        result: true,
                        type: 1,
                    });
                }

                if (self.game_type === 4 && !self.zhuang_user && self.qiang_time <= 0) {   //抢庄结束
                    log.info("结束抢庄");
                    var z_obj = {user: 0, score: 0};
                    for (var q_z in self.qiang_zhuang_list) {
                        var q_obj = self.qiang_zhuang_list[q_z];
                        if (q_obj.score > z_obj.score) {
                            z_obj = q_obj
                        }
                    }

                    if (z_obj.user && self.userList[z_obj.user]) {
                        self.game_type = 0;
                        self.zhuang_user = z_obj.user;
                        self.zhuang_robot = self.userList[z_obj.user]._Robot;
                        self._io.sockets.emit('sendZhuang', {
                            result: true,
                            zhuang: self.zhuang_user,
                            name: self.userList[self.zhuang_user]._nickname,
                            url: self.userList[self.zhuang_user]._headimgurl,
                            zCoin: self.userList[self.zhuang_user].getScore(),
                        });
                    } else {
                        self.game_type = 3;  //没有庄 从新设置状态
                        self.qiang_zhuang_list = [];
                        self.zhuang_user = 0;    //置空庄家
                        self.bet_user_pool = [0, 0, 0, 0, 0, 0, 0, 0];
                        self.zhuang_robot = false;
                    }

                }

                if (self.qiang_time > 0) {
                    self.qiang_time--;
                }


                if (self.bet_time > 0) {
                    self.bet_time--;
                    self._io.sockets.emit('BetPool', {
                        betPool: self.bet_user_pool
                    });
                }

                if (self.feng_time > 0) {
                    self.feng_time--;
                }
                self.game_second = second;
                if (self.zhuang_user && self.game_type == 0) {    //有庄就开局
                    log.info("开始下注  清除数组");
                    redis_dao.init_bet_list();
                    self.game_type = 1;
                    self.bet_time = gameConfig.xzTime;
                    self._io.sockets.emit('BetStart', {
                        result: true,
                        type: 1,
                    });

                }
                if (self.bet_time <= 0 && self.game_type == 1) {
                    self.feng_time = gameConfig.fpTime;
                    self.game_type = 5;
                }

                if (self.feng_time <= 0 && self.game_type == 5) {
                    log.info("开奖");
                    //开奖
                    self.game_type = 2;
                    self.open_win();
                }

                if (second == 0) {
                    redis_send_and_listen.send_msg("OnlineUserMsg", {
                        server_id: gameConfig.serverId,
                        online_num: self.onlinePlayerCount
                    });
                    //log.info("推送在线人数");
                }
            });
        };

        this.tt = 0;

        this.lottery = function (_userId, _nBetList) {
            //用户_userid 摇奖
            //返回-1 未登录
            //返回-2 资金不足
            //返回-3 非下注时间
            if (this.game_type != 1) {		//不是下注时间
                log.info("不是下注时间");
                return {code: -3};
            }

            if (!_userId) {					//传输ID错误
                log.info("未传用户ID");
                return {code: -1};
            }
            if (!this.userList[_userId]) {	//未找到用户
                log.info("找不到用户");
                return {code: -1};
            }

            //下注
            let bet_dict = _nBetList;
            let nBetSum = 0;
            //统计当前下注总额
            for (let i = 0; i < this.bet_user_pool.length; i++) {
                nBetSum += this.bet_user_pool[i];
            }
            nBetSum += bet_dict.bet_gold;

            //判断是否足够赔付
            if (gameConfig.GAME_COLORS_FRUIT_MACHINE[bet_dict.bet_res] * bet_dict.bet_gold > gameConfig.betMax + nBetSum) {
                log.info("奖池满了不能下注了", this.bet_user_pool[bet_dict.bet_res]);
                return {code: -1};
            }

            //用户扣钱
            var lotteryResult = this.userList[_userId].lottery(bet_dict.bet_gold);
            if (!lotteryResult) {
                log.info(_userId + "分数不够");
                return {code: -2};
            }

            this.bet_user_pool[bet_dict.bet_res] += bet_dict.bet_gold;


            var GamblingBalanceLevelBigWin = this.A.getGamblingBalanceLevelBigWin(); //获取库存 水位 大奖幸运值
            //水位  抽水
            var nGamblingWaterLevelGold = GamblingBalanceLevelBigWin.nGamblingWaterLevelGold;


            var addBalanceGold = parseInt(bet_dict.bet_gold * parseFloat(nGamblingWaterLevelGold / 100));    //进入库存的钱
            var addWinPool = bet_dict.bet_gold - addBalanceGold;                  //进入奖池的钱


            //增加库存和奖池

            if (!this.userList[_userId]._Robot) {
                this.A.addGamblingBalanceGold(addBalanceGold, addWinPool);
            }

            bet_dict["userId"] = _userId;
            if (this.userList[_userId]._Robot) {
                bet_dict["is_robot"] = true;
            } else {
                bet_dict["is_robot"] = false;
            }
            //添加数据
            try {
                redis_dao.save_bet(bet_dict);
            } catch (e) {
                log.info("下注添加数据报错")
            }


            return {code: 2, bet_dict: bet_dict}

        };

        this.open_win = function () {
            log.info("开始开奖");
            if (this.game_type != 2) {
                log.info("game_type不是2 不能开奖:" + this.game_type);
                return;
            }
            //开奖
            //获取下注数据
            redis_dao.get_bet_list().then(res => {
                let redis_dict = res;
                let GamblingBalanceLevelBigWin = this.A.getGamblingBalanceLevelBigWin(); //获取库存 水位 大奖幸运值
                //奖池
                let nGamblingWinPool = GamblingBalanceLevelBigWin.nGamblingWinPool;

                let user_bet_list = {};
                for (let i in redis_dict) {
                    let betInfo = redis_dict[i];   //下注详情
                    let res = parseInt(betInfo.bet_res);
                    if (!user_bet_list[betInfo["userId"]]) {
                        user_bet_list[betInfo["userId"]] = {userId: betInfo["userId"]}
                    }
                    if (!user_bet_list[betInfo["userId"]][res]) {
                        user_bet_list[betInfo["userId"]][res] = 0;
                    }
                    user_bet_list[betInfo["userId"]][res] += parseInt(betInfo["bet_gold"]);

                }

                // log.info("下注信息--------------------------------------")
                // log.info(redis_dict)

                let zhuang_robot = this.zhuang_robot;

                let is_robot = false;
                if (zhuang_robot) {    //庄家是否为机器人
                    is_robot = true;
                }
                let dictAnalyseResults = {};
                dictAnalyseResults = this.A.gameProcessor(redis_dict, nGamblingWinPool, is_robot);//结果

                dictAnalyseResults["user_bet_list"] = user_bet_list; //下注详情

                // log.info(dictAnalyseResults)

                let user_robot_dict = dictAnalyseResults["user_robot_dict"];

                let betscore = 0;    //下注总额
                let jia_betscore = 0;    //下注总额
                for (var i in dictAnalyseResults["user_bet_sum_list"]) {
                    var user_bet = dictAnalyseResults["user_bet_sum_list"][i];
                    jia_betscore += user_bet;
                    if (!user_robot_dict[i]) {
                        betscore += user_bet;
                    }
                }

                let winscore = 0;
                let jia_winscore = 0;
                for (let i in dictAnalyseResults["win_user_list"]) {
                    let user_win = dictAnalyseResults["win_user_list"][i];
                    jia_winscore += user_win;
                    if (!user_robot_dict[i]) {
                        winscore += user_win;
                    }
                    if (user_robot_dict[i] && !zhuang_robot) {
                        this.A.addGamblingBalanceGold(0, parseInt(user_win / 2));
                    }
                    this.GameBalance(i, user_win);
                }

                let zhuangscore = betscore - winscore;
                // log.info("下注前-------------------",betscore);
                // log.info("下注后-------------------",winscore);
                // log.info("-------------------",zhuangscore)

                this.GameBalance(this.zhuang_user, zhuangscore);

                if (zhuang_robot && zhuangscore < 0) {
                    this.A.addGamblingBalanceGold(0, zhuangscore);
                }

                dictAnalyseResults["zhuangscore"] = jia_betscore - jia_winscore;  //假数据
                //制作结果
                var result = {
                    ResultCode: 1,
                    win_res: dictAnalyseResults["win_res"],
                    zhuangscore: zhuangscore,
                };
                log.info("开奖结果:", result);
                // log.info(dictAnalyseResults["win_user_list"]);

                var user_win_list = dictAnalyseResults["win_user_list"];
                //推消息
                for (let u in this.userList) {

                    var send_data = {
                        win_res: dictAnalyseResults["win_res"],
                        win_car: dictAnalyseResults["win_car"],
                    };
                    let user_win = 0;
                    if (user_win_list) {
                        if (user_win_list[u]) {
                            user_win = user_win_list[u];
                        }
                    }
                    if (parseInt(this.zhuang_user) == parseInt(u)) {
                        user_win = zhuangscore;
                    }

                    send_data["user_win"] = user_win;

                    this.userList[u]._socket.emit('OpenWinResult', send_data);
                }
                
                //1.写记录
                var user_bet_sum_list = dictAnalyseResults["user_bet_sum_list"];
                var CoinLog = [];
                for (var i in user_win_list) {
                    if (i <= 10000) {
                        continue;
                    }
                    log.info("insert mark bet sum: " + user_bet_sum_list[i]);

                    var logTemp = {
                        userId: parseInt(i),
                        useCoin: user_bet_sum_list[i],
                        winCoin: user_win_list[i],
                        tax: 0,
                        serverId: gameConfig.serverId,
                        gameId: gameConfig.gameId
                    };
                    CoinLog.push(logTemp);
                }
                this._Csocket.emit("insertMark", CoinLog);

                this.zhuang_user = 0;    //置空庄家
                this.qiang_zhuang_list = [];
                this.zhuang_robot = false;
                this.bet_user_pool = [0, 0, 0, 0, 0, 0, 0, 0];
                //保存奖池
                this.saveGamblingBalanceGold();
                //存日志
                dictAnalyseResults["open_time"] = Number(new Date());
                gameDao.saveGameLog(JSON.stringify(dictAnalyseResults));

                this.game_record_list.push(dictAnalyseResults);
                if (this.game_record_list.length > 20) {
                    this.game_record_list.splice(0, 1)
                }
                setTimeout(() => {
                    this.game_type = 3;   //状态设置为结束
                }, gameConfig.jsTime * 1000);


            }).catch(e => {

            })


        };

        this.setIo = function (_io, _Csocket) {
            this.sever.setIo(_io, _Csocket);
            this._io = _io;
            this._Csocket = _Csocket;
        };


        this.Setmaintain = function () {
            gameConfig.maintain = true;
        };

        this.isMaintain = function () {
            return gameConfig.maintain;
        };

        //判断是否是同一scoket连续登录，不允许
        this.isLoginAgain = function (socket) {
            if (socket.userId) {
                return this.userList[socket.userId].Islogin();
            } else {
                return false;
            }
        };

        //添加用户
        this.addUser = function (_userInfo, socket) {
            this.userList[_userInfo.userid] = new User(_userInfo, socket);
        };

        this.updateUser = function (userInfo) {
            //log.info("update")
            if (!this.userList[userInfo._userId]) return;

            //已经断线
            if (this.userList[userInfo._userId]._isLeave) {
                var result = {ResultCode: 0, userId: userInfo._userId};
                this._Csocket.emit("userDisconnect", result);
                delete this.userList[userInfo._userId];
                return;
            }
            this.userList[userInfo._userId].update(userInfo);

            this.LoginGame(userInfo._userId, this.serverId);
            ++this.onlinePlayerCount;

            var self = this;
            var resultObj = {
                account: self.userList[userInfo._userId]._account,
                id: self.userList[userInfo._userId]._userId,
                nickname: self.userList[userInfo._userId]._nickname,
                score: self.userList[userInfo._userId]._score
            };
            result = {resultid: '1', msg: 'login lineserver succeed!', Obj: resultObj};
            this.userList[userInfo._userId]._socket.emit('loginGameResult', result);

        };

        //获得在线人数
        this.getOnlinePlayerCount = function () {
            return this.onlinePlayerCount;
        };

        //在线所有人
        this.getOnlinePlayer = function () {
            return this.userList;
        };

        this.score_changeLog = function () {
            var self = this;
            var saveListTemp = [];
            var ItemTemp;
            var max = 0;
            if (this.score_changeLogList.length > 200) {
                max = 200;
            } else {
                max = this.score_changeLogList.length;
            }
            for (var i = 0; i < max; i++) {
                if (this.score_changeLogList.length > 0) {
                    ItemTemp = this.score_changeLogList.shift();
                    saveListTemp.push(ItemTemp);
                }
            }
            if (saveListTemp.length > 0) {
                this._Csocket.emit("score_changeLog", saveListTemp);
                //gameDao.score_changeLog(saveListTemp);
            }
        }

        this.lotteryLog = function () {
            var self = this;
            var saveListLotteryLogTemp = [];
            var ItemTemp;
            var max = 0;
            if (this.lotteryLogList.length > 200) {
                max = 200;
            } else {
                max = this.lotteryLogList.length;
            }
            for (var i = 0; i < max; i++) {
                if (this.lotteryLogList.length > 0) {
                    ItemTemp = this.lotteryLogList.shift();
                    saveListLotteryLogTemp.push(ItemTemp);
                }
            }
            if (saveListLotteryLogTemp.length > 0) {
                gameDao.lotteryLog(saveListLotteryLogTemp);
            }
        };

        this.GameBalance = function (userItem, userWin) {
            log.info("GameBalance");
            log.info(userItem, userWin);
            //判断玩家是否在线
            if (this.userList[userItem]) {
                var youScore = this.userList[userItem].getScore();
                this.userList[userItem].winscore(userWin);
                var youNowScore = this.userList[userItem].getScore();
                //记录金钱变化量
                var userInfolog = {
                    userid: userItem,
                    score_before: youScore,
                    score_change: userWin,
                    score_current: youNowScore,
                    change_type: gameConfig.logflag,
                    isOnline: true
                };
                this.score_changeLogList.push(userInfolog);
            } else {
                this._Csocket.emit("GameBalance", {
                    signCode: gameConfig.LoginServeSign,
                    sendUserId: userItem,
                    sendCoin: userWin,
                    change_type: gameConfig.logflag
                })
            }
        };

        //删除用户
        this.deleteUser = function (_socket) {
            if (_socket.userId) {
                //存免费次数
                var info = {
                    userId: _socket.userId,
                    freeCount: this.userList[_socket.userId].getFreeCount(),
                    LotteryCount: this.userList[_socket.userId].getLotteryCount()
                };
                gameDao.saveFree(info, function (result) {
                    if (!result)
                        log.err("存免费次数:" + _userinfo.userId + "失败!")
                });
                this._Csocket.emit("lineOut", {
                    signCode: gameConfig.LoginServeSign,
                    state: 0,
                    gameId: gameConfig.gameId,
                    serverId: gameConfig.serverId,
                    userId: _socket.userId,
                    tableId: -1,
                    seatId: -1
                });
                this.sever.LogoutRoom(this.userList[_socket.userId], _socket);
                delete this.userList[_socket.userId];
                --this.onlinePlayerCount;
            }
        };

        //删除用户
        this.deleteUserById = function (_userId, msg) {
            if (_userId) {
                var socketItem = this.userList[_userId]._socket;
                result = {resultid: 0, msg: msg};
                socketItem.emit('loginGameResult', result);
                delete this.userList[_userId];
            }
        };

        //获得用户当前分数
        this.getUserscore = function (_userId) {
            if (_userId) {
                return this.userList[_userId]._score;
            }
        };

        //获得用户
        this.getUser = function (_userId) {
            if (_userId) {
                return this.userList[_userId];
            }
        };

        //用户是否在线
        this.IsPlayerOnline = function (_userId) {
            if (!_userId) {	//传输ID错误
                log.info("查询在线,参数错误");
                return -1;
            }
            if (this.userList[_userId]) {//未找到用户
                //log.info("查询在线,未找到" + _userId + "用户");
                return 1;
            } else {
                return 0;
            }
        };

        //获得用户当前分数
        this.getPlayerScore = function (_userId) {
            if (!_userId) {	//传输ID错误
                log.info("查询分数,参数错误");
                return -1;
            }
            if (this.userList[_userId]) {//未找到用户
                //log.info("查询在线,未找到" + _userId + "用户");
                return this.userList[_userId].getScore();
            } else {
                return -1;
            }
        };

        //GM加分
        this.addgold = function (_userId, score) {

            if (!_userId) {					//传输ID错误
                log.info("加分,未登录");
                return 0;
            }
            if (!this.userList[_userId]) {	//未找到用户
                log.info("加分,未登录");
                return 0
            } else {
                log.info(score);
                if (this.userList[_userId].addgold(score)) {
                    log.info(this.userList[_userId].getScore());
                    log.info("加分成功!")
                    var tablestring = "table" + this.userList[_userId].getTable();
                    this._io.sockets.in(tablestring).emit('addgoldResult', {
                        userId: _userId,
                        userSeatId: this.userList[_userId].getSeat(),
                        userScore: this.userList[_userId]._score
                    });
                    return 1;
                } else {
                    log.info("减分失败,大于用户分数!");
                    return 0;
                }
            }
        };

        //保存库存 奖池
        this.saveGamblingBalanceGold = function () {
            //获得库存奖池
            var dict = this.A.getGamblingBalanceGold();

            gameDao.Update_GamblingBalanceGold(dict.nGamblingBalanceGold, dict.nGamblingWinPool, function (Result) {
            })
        };


        //进入游戏
        this.LoginGame = function (_userId, gametype) {
            if (!this.userList[_userId]) return;
            //用户添加游戏ID
            //log.info(_userId)
            //log.info("用户进入游戏" + gametype);
            this.userList[_userId].loginGame(gametype);
        };

        //断线保存
        this.lineOutSet = function (_info) {
            if (_info.state == 1) {
                //添加
                this.lineOutList[_info.userId] = {tableId: _info.tableId, seatId: _info.seatId}
                //log.info(this.lineOutList[_info.userId]);
            } else {
                //移除
                this._Csocket.emit("lineOut", {
                    signCode: gameConfig.LoginServeSign,
                    state: 0,
                    gameId: gameConfig.gameId,
                    userId: _info.userId
                });
                delete this.lineOutList[_info.userId];
            }
        };

        //获得断线用户信息
        this.getLineOutMsg = function (_userId) {
            if (this.lineOutList[_userId]) {
                this.lineOutList[_userId].Result = 1;
                return this.lineOutList[_userId];
            } else {
                return {Result: 0};
            }
        };

        //清楚断线用户信息
        this.cleanLineOut = function () {
            //清理登录服务器
            log.info(this.lineOutList);
            for (var Item in this.lineOutList) {
                Item = parseInt(Item);
                var tableid = this.lineOutList[Item].tableId;
                var tablestring = "table" + tableid;
                this._io.sockets.in(tablestring).emit('PlayerOut', {
                    PlayerSeatId: this.lineOutList[Item].seatId,
                    userId: Item
                });
                this.sever.cleanLineOut(tableid, this.lineOutList[Item].seatId);
                this._Csocket.emit("lineOut", {
                    signCode: gameConfig.LoginServeSign,
                    state: 0,
                    gameId: gameConfig.gameId,
                    userId: Item
                })
            }
            this.lineOutList = {};
        };

        this.getDownTime = function (_socket) {
            if (!this.userList[_socket.userId]) {
                //log.info("用户" + _socket.userId + "不存在");
                return;
            }

            var tableid = this.userList[_socket.userId].TableId;
            if (tableid < 0) {
                _socket.emit("getDownTimeResult", {ResultCode: 0, msg: "用户没有进入桌子"});
                return;
            }

            if (this.upUserList[tableid].length == 0) {
                _socket.emit("getDownTimeResult", {
                    ResultCode: 1,
                    downTime: this.sever.downTime,
                    upUserList: [],
                    upCoin: 0,
                    DownCoin: [0, 0, 0],
                    myDownCoin: [0, 0, 0]
                });
                return;
            }

            let down1 = 0;
            let down2 = 0;
            let down3 = 0;
            for (let itme in this.downCoinList[tableid]) {
                down1 += this.downCoinList[tableid][itme][0];
                down2 += this.downCoinList[tableid][itme][1];
                down3 += this.downCoinList[tableid][itme][2];
            }

            let mydown1 = 0;
            let mydown2 = 0;
            let mydown3 = 0;
            if (this.downCoinList[tableid][_socket.userId]) {
                mydown1 = this.downCoinList[tableid][_socket.userId][0];
                mydown2 = this.downCoinList[tableid][_socket.userId][1];
                mydown3 = this.downCoinList[tableid][_socket.userId][2];
            }

            //每门下注额度
            _socket.emit("getDownTimeResult", {
                ResultCode: 1,
                downTime: this.sever.downTime,
                upUserList: this.upUserList[tableid],
                upCoin: this.upUserList[tableid][0].upCoin,
                DownCoin: [down1, down2, down3],
                myDownCoin: [mydown1, mydown2, mydown3]
            });
        };


        this.disconnectAllUser = function () {
            for (let itme in this.userList) {
                this.userList[itme]._socket.disconnect();
            }
            log.info("服务器开启维护，已经全部离线");
        };

        //运行初始化
        this.init();
    };


    if (_gameinfo) {
        return {getInstand: _gameinfo}
    } else {
        log.info("####create game!####");
        _gameinfo = new Game();
        return {getInstand: _gameinfo}
    }

}();

function RandomNumBoth(Min, Max) {
    //生成指定范围内随机整数
    var Range = Max - Min;
    var Rand = Math.random();
    var num = Min + Math.round(Rand * Range); //四舍五入
    return num;
}


module.exports = GameInfo;

